% cm_free.m
% 释放一个 buffer，并合并相邻的空闲内存块。
% (版本 15: 使用更健壮的合并逻辑)

function manager = cm_free(manager, buf_id_to_free)
    alloc_idx = -1;
    for i = 1:length(manager.allocated_blocks)
        if manager.allocated_blocks(i).buf_id == buf_id_to_free
            alloc_idx = i;
            break;
        end
    end
    
    if alloc_idx == -1, return; end

    new_free_block = manager.allocated_blocks(alloc_idx);
    manager.allocated_blocks(alloc_idx) = [];

    % 插入并保持 free_blocks 有序
    manager.free_blocks = [manager.free_blocks; new_free_block];
    if ~isempty(manager.free_blocks)
        [~, sort_idx] = sort([manager.free_blocks.start]);
        manager.free_blocks = manager.free_blocks(sort_idx);
    end

    % --- 合并空闲块 (更健壮的实现) ---
    if length(manager.free_blocks) < 2
        return; % 如果不足2个块，则无需合并
    end
    
    new_free_blocks = manager.free_blocks(1); % 从第一个块开始
    for i = 2:length(manager.free_blocks)
        last_block_idx = length(new_free_blocks);
        current_block = manager.free_blocks(i);
        
        % 检查当前块是否能与新列表的最后一个块合并
        if new_free_blocks(last_block_idx).start + new_free_blocks(last_block_idx).size == current_block.start
            % 合并: 只增加最后一个块的大小
            new_free_blocks(last_block_idx).size = new_free_blocks(last_block_idx).size + current_block.size;
        else
            % 不合并: 将当前块追加到新列表的末尾
            new_free_blocks = [new_free_blocks; current_block];
        end
    end
    manager.free_blocks = new_free_blocks; % 替换为合并后的新列表
end